﻿' Copyright (C) 2015 HTTPBuilder
'
' This program is free software: you can redistribute it and/or modify it under the +terms 
' of the GNU General Public License as published by the Free Software Foundation, either 
' version 3 of the License, or (at your option) any later version.

' This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
' without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
' See the GNU General Public License for more details.

' You should have received a copy of the GNU General Public License along with this program.
' If not, see http://www.gnu.org/licenses/. 

Imports System.Text
Imports HTTPBuilder.Extensability

''' <summary>
''' 
''' </summary>
''' <remarks></remarks>
Public NotInheritable Class XmlFormatter
    Implements IFormatter

#Region "Member variables"
    Private ReadOnly _walker As StringWalker
    Private ReadOnly _writer As New IndentWriter("  ")
    Private ReadOnly _currentLine As New StringBuilder()
    Private _inCloseBracket As Boolean
    Private _inBracket As Boolean
#End Region

#Region "Constructor"
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="json"></param>
    ''' <remarks></remarks>
    Public Sub New(json As String)
        _walker = New StringWalker(json)
        ResetLine()
    End Sub
#End Region

#Region "Public methods"
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub ResetLine()
        _currentLine.Length = 0
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IsOpenBracket() As Boolean
        Return Me._walker.CurrentChar = "<"c 'OrElse Me._walker.CurrentChar = "["c
    End Function
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IsTrailingBracket() As Boolean
        Return Me._walker.CurrentChar = "/" AndAlso
            (Me._walker.PreviousChar = "<" OrElse Me._walker.NextChar = ">")
    End Function
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IsCloseBracket() As Boolean
        Return Me._walker.CurrentChar = ">"c 'OrElse Me._walker.CurrentChar = "]"c
    End Function

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Format() As String Implements IFormatter.Format
        While MoveNextChar()
            If IsOpenBracket() Then '<
                _inBracket = True
                AddCharToLine()
            ElseIf IsCloseBracket() Then ' >
                _inBracket = False
                If _inCloseBracket Then ' </tag> or <tag />'
                    _writer.Outdent()
                    AddCharToLine()
                    Me.WriteCurrentLine()
                    _inCloseBracket = False
                Else ' <tag>
                    ''If _walker.ReadNext(2) = "</" Then
                    ''    AddCharToLine()
                    ''    'Me.WriteCurrentLine()
                    ''    _writer.Indent()
                    ''Else
                    ''    AddCharToLine()
                    ''    Me.WriteCurrentLine()
                    ''    _writer.Indent()
                    ''End If
                    AddCharToLine()
                    Me.WriteCurrentLine()
                    _writer.Indent()
                End If
            ElseIf IsTrailingBracket() AndAlso _inBracket Then ' <... /
                _inCloseBracket = True
                AddCharToLine()
            Else
                ' anything else than <, > or /
                ' good to debug structure - comment out
                AddCharToLine()
            End If
        End While
        Me.WriteCurrentLine()

        Return _writer.ToString()
    End Function
#End Region

#Region "Private methods"
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub AddCharToLine()
        Me._currentLine.Append(_walker.CurrentChar)
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub WriteCurrentLine()
        Dim line As String = Me._currentLine.ToString().Trim()
        If line.Length > 0 Then
            _writer.WriteLine(line)
        End If
        Me.ResetLine()
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function MoveNextChar() As Boolean
        Dim success As Boolean = _walker.MoveNext()
        'If Me.IsApostrophe() Then
        '    Me._quoted = Not _quoted
        'End If
        Return success
    End Function
#End Region
End Class
